#if !defined(ximera_graphics_ogre_scenenode_hpp)
#define ximera_graphics_ogre_scenenode_hpp

// -----------------------------------------------------------

#include <ximera/graphics/iscenenode.hpp>
#include <ximera/common/sharedptr.hpp>

#include <OgreSceneNode.h>
#include <vector>

namespace ximera { namespace graphics { namespace ogre
{
    class World;
    class GraphicsSystem;

    class XIMERA_PLUGIN_API SceneNode : public ISceneNode
    {
    public:
        SceneNode(World* world, GraphicsSystem* graphicsSystem, String const& name = L"");
        SceneNode(World* world, SceneNode* parent, String const& name = L"");
        SceneNode(World* world, Ogre::SceneNode* node);
        virtual ~SceneNode();

        virtual IWorld* world();

        virtual math::Vector3 position() const;
        virtual void position(math::Vector3 const& pos);

        virtual math::Quaternion orientation() const;
        virtual void orientation(math::Quaternion const& quat);

        virtual math::Matrix3 orientationMatrix() const;
        virtual void orientationMatrix(math::Matrix3 const& orient);

        virtual void scale(Real scale);
        virtual void scale(Real x, Real y, Real z);
        virtual void scale(math::Vector3 const& scale);

        virtual void roll(Real angle);
        virtual void yaw(Real angle);
        virtual void pitch(Real angle);

        virtual void direction(math::Vector3 const& dir);
        virtual void lookAt(math::Vector3 const& point);

        virtual String const& name() const;
        virtual void name(String const& name);

        virtual ISceneNode* parent() const;

        virtual UInt32 childCount() const;
        virtual ISceneNode* child(UInt32 index) const;

        virtual ISceneNode* createChild(String const& name = L"");
        virtual void addChild(ISceneNode* node);
        virtual void removeChild(ISceneNode* node);
        virtual void removeAllChildren();

        virtual bool isChild(ISceneNode* node);

        virtual ISceneNode* findChild(String const& name);
        virtual ISceneNode* findDescendant(String const& name);

        virtual void attach(Attachable* object);
        virtual void detach(Attachable* object);

        Ogre::SceneNode* ogreSceneNode() const { return _ogreSceneNode; }
        void parent(SceneNode* node) { _parent = node; }

    private:
        typedef std::vector<ISceneNode*> NodeContainer;
        typedef std::vector<Attachable*> AttachableContainer;

        World* _world;
        SceneNode* _parent;
        String _name;
        NodeContainer _children;
        AttachableContainer _attached;

        Ogre::SceneNode* _ogreSceneNode;
    };
}}}

// -----------------------------------------------------------

#endif